home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1996 #15
/
Monster Media Number 15 (Monster Media)(July 1996).ISO
/
win_utl1
/
giveup2.zip
/
GIVE-UP.ASM
next >
Wrap
Assembly Source File
|
1996-03-23
|
33KB
|
410 lines
; This program calls Int 2F, function 1680h, to give OS/2, Desqview, etc.
; a chance to use wasted CPU cycles.
;
; The program also hooks the DOS multiplex interrupt, Int 2Fh, for an installation check.
;
; 08 Nov. 1995 -- 1st release -- Gives up just a little too much. Needs major work!!
;
; 09 Nov. 1995 -- 2nd release -- Fixed screwup in TSR paragraph calculation. Does not
; noticeably return CPU cycles, but no more bizarro
; lockups and segment faults.
;
; 10 Nov. 1995 -- 3rd release -- Modified code to use Int 2F, Function 1680h, Release
; current virtual machine time slice, instead of just
; calling the DOS idle interrupt. Found this in PC
; Interrupts, 2nd edition. Works well, but needs some
; tuning parameters added. Giving up slices 18 times
; a second is a bit much.
;
; 11 Nov. 1995 -- 4th release -- Began adding tuning parameters. Fixed a bug in the int 1C
; ISR. The IRET in the old int 2F handler was popping AX
; instead of the flags. Rearranged the push ax and the pushf
; to fix it.
;
; 23 Nov. 1995 -- 5th release -- Added elapsed tick counter, and logic to increment it on every
; timer tick, to the int 1C isr. In order to make this work, I
; had to use the CS segment override on the inc instruction. I
; intend to use this to trigger the call to int 2F, function 1680h
; after so many ticks as opposed to every one.
; -- Added whenmask to hold a value for controlling when to release a
; CPU cycle. Essentially I AND elapsed with whenmask, and if the
; is not zero then it's time to release a CPU cycle. Currently
; whenmask is set at 4, so int 2F, function 1680h is getting
; called every 4 ticks instead of every tick.
;
; 24 Nov. 1995 -- 6th release -- Corrected bug with the trigger logic. Logical AND is not the
; proper way to do this, because it does not cause the event
; to happen every whenmask ticks. Changed it to use straight
; comparison, and elapsed to reflect ticks since last event.
; It is much smoother now.
; -- Added code in the installation portion of the program to find
; the trigger interval on the command line passed as /XX where
; for the present both digits must be passed. XX can range from
; 0 to 99. If nothing is passed, the default is every 4 ticks.
;
; 24 Nov. 1995 -- 7th release -- Changed the ownership message to reflect the Bionic Fish
; Software Foundry. This is preparatory to releasing as freeware.
; Freeware release will occur 24 Nov. 1995 via upload to EXEC-PC.
;
; 20 Feb. 1996 -- 8th release -- Began working on V1R8. Will not allow Disk I/O or Mouse operations
; to be interrupted. This will be accomplished by creating a
; semaphore variable, and using it control whether the interruption
; occurs when it is supposed to. Instead, it will reset the counter
; to zero, and IRET. The mouse will be done first, and I am going
; to assume the mouse is MS compatible, and has an Int 33h API.
; -- Code for the mouse exclusion is in place. Sema is the semaphore
; variable. 0 = activation allowed, >0 = activation NOT allowed.
; Because I will also use this semaphore for the Disk I/O, I must
; accept that the semaphore may be greater than 1, because a disk
; event may be interrupted by a mouse event and vice versa.
; -- Code for trapping int 33h, mouse api, is in place. A simple wrapper,
; it should cause extremely minimal performance degradation.
; -- Because of the code required for hooking the mouse interrupt, the
; conditional jmp at the end of the install_chek had to be modified.
; The conditional jump now checks if installation has not occured, and
; bypasses the unconditional jmp if it has NOT.
; -- Code for Disk I/O trapping, BIOS int 13h, is in place. Same concept
; as the mouse trap.
; -- With both of these changes in place, performance in a full screen DOS
; session under OS/2 Warp with the interval set at 6 ticks, AutoSketch
; runs noticeably better than it did, but not better enough. More work
; must be done to improve overall system performance. However, I am
; putting it into production on my system today.
;
; 08 Mar. 1996 -- 9th release -- Added code to retrieve the address of the In-DOS flag during the install
; phase. The address is stored in the indos_flg variable. I have not
; decided how to use the In-DOS flag, however.
; -- Added code to retrieve the address of the DOS Critical Error flag. The
; address is stored in the crter_flg variable. As with the In-DOS flag,
; I haven't decided how to use it.
; -- Changed the jne conditional jump in the elapsed to whenmask comparison
; to a jb jump. This will guarantee that the release will happen and
; get resynchronized if elapsed should happen to become greater than
; whenmask.
; -- Added code to the Int 1C isr to check the In-DOS flag and prevent
; activation if set.
; -- Added code to the Int 1C isr to check the Critical Error flag and
; prevent activation if set.
; -- Removed Hard Disk BIOS & Mouse Semaphores. The Critical Error and
; In-DOS flag checks do much better.
; -- Added code to hook the DOS Idle Interrupt, Int 28h. Since the In-DOS
; flag is set during an Int 28h call, it is necessary to hook this in
; order for cycles to be released during input wait loops. Unlike the
; Int 1Ch isr, the Int 28h service routine releases cycles every time
; it is invoked.
; -- Works great!! The only hitch is a slower ramp up to maximum file xfer
; speed in Telix for Windows. However, the fact that Windows runs under
; OS/2 Warp with give-up being loaded in the OS/2 autoexec.bat speaks
; major things about this release. It goes into production in my OS/2
; autoexec.bat today. This means every WIN-OS/2 session will have give-up
; running in the background.
;
; 09 Mar. 1996 --10th release -- The final modification before releasing this as a new version is a change
; to the loader. Instead of executing and then going TSR, I think it
; allocate a block of DOS memory as high in MCB chain as possible, copy
; only the ISRs and their data into it, changing the allocated MCB's
; owner to 0x08h, MS-DOS, linking the ISRs into the IVT chains, and then
; exiting normally. By allocating the memory from the top, a hole will
; not be left when the loader portion terminates. In order for this to work,
; it is necessary to reallocate the MCB used by give-up itself.
; -- Added code to reallocate the Give-up MCB to only the actual amount used.
; -- Added code to allocate a block of memory and then change its owner to DOS.
; This block of memory will not get released when the program terminates.
; -- Added code to calculate the new ISR offsets. When the code is moved into
; the new segment, the offsets will be true offsets from the beginning of
; the segment, as opposed to the beginning of a .COM program where the PSP
; must be accounted for.
; -- Added code to copy the ISR code and data to its new location in memory.
; -- Removed TSR memory calculation and TSR exit code. Also changed the exit
; label from not_tsr_exit to plain exit.
; -- Because all of the original offsets and addresses are calculated with an
; ORG of 256 because this starts as a .COM program, I had to adjust all of
; the offsets in variable and address references in the ISR routines.
; These are the -256 additions throughout this sections of the code.
; -- Works!! memory footprint is a mere 160 bytes!! Going into production use.
;
; 23 Mar. 1996 --11th release -- Officially changing the version from v1r10 to v2r1, and corrected the startup
; message to reflect this. Will release to Exec-pc on Sunday, 24 Mar. 1996.
_CODE SEGMENT
ASSUME CS:_CODE, DS:_CODE, ES:_CODE
ORG 100h
start:
jmp install ; Jump to the installation code
oldint1c dd 00000000h ; Old int 1Ch, timer, ivt entry
oldint28 dd 00000000h ; Old int 28h, DOS Idle, ivt entry
oldint2f dd 00000000h ; Old int 2Fh, multiplex, ivt entry
indos_flg dd 00000000h ; Address of In-DOS flag
crter_flg dd 00000000h ; Address of Critical Error Flag
elapsed dw 0000h ; Ticks elapsed since program load
whenmask dw 0004h ; When to activate
int28_isr: ; Interrupt 28h, ISR
pushf ; Push flags onto stack
call cs:oldint28-256 ; Transfer control to old interrupt handler
push ax ; Preserve AX
mov ax,1680h ; Int 2F, function 1680h, Release current time slice
pushf ; Push flags onto stack
call cs:oldint2f-256 ; Call multiplex interrupt
pop ax ; Restore AX
iret ; Interrupt return
int2f_isr: ; Interrupt 2Fh ISR
cmp ax,0BADDh ; 0xBADD is my multiplex ID
je int2f_isr_srvc ; If AX=0xBADDh then service the request
jmp cs:oldint2f-256 ; Transfer control to old int 2Fh ISR otherwise
int2f_isr_srvc: ; Custom int 2Fh code is here
mov ax,0FADEh ; AX=0xFADEh, then GIVE-UP is installed
iret ; Interrupt return
int1c_isr: ; Interrupt 1Ch ISR
pushf ; Push flags onto stack
call cs:oldint1c-256 ; Transfer control to the old interrupt handler
push bx ; Preserve BX
mov bx,word ptr cs:[elapsed-256] ; Copy to temporary storage
cmp bx,word ptr cs:[whenmask-256] ; Is it time to trigger
pop bx ; Restore BX
jb int1c_isr_inc ; If less than then increment elapsed and return
push ax ; Preserve AX
push bx ; Preserve BX
push es ; Preserve ES
mov ax,0001h ; Set AX to 1
mov bx,word ptr cs:[indos_flg+2-256] ; Point ES to In-DOS flag
mov es,bx
mov bx,word ptr cs:[indos_flg-256] ; Point BX to In-DOS flag
cmp al,byte ptr es:[bx] ; See if In-DOS flag is set
pop es ; Restore ES
pop bx ; Restore BX
pop ax ; Restore AX
jae int1c_isr_reset ; If In-DOS is set reset elapsed and return
push ax ; Preserve AX
push bx ; Preserve BX
push es ; Preserve ES
mov ax,0001h ; Set AX to 1
mov bx,word ptr cs:[crter_flg+2-256] ; Point ES to Critical Error flag
mov es,bx
mov bx,word ptr cs:[crter_flg-256] ; Point BX to Critical Error flag
cmp al,byte ptr es:[bx] ; See if Critical Error flag is set
pop es ; Restore ES
pop bx ; Restore BX
pop ax ; Restore AX
jae int1c_isr_reset ; If Critical Error is set reset elapsed and return
push ax ; Preserve AX
mov ax,1680h ; Int 2F, function 1680h, Release current time slice
pushf ; Push flags onto stack
call cs:oldint2f-256 ; Call multiplex interrupt
pop ax ; Restore AX
int1c_isr_reset:
mov word ptr cs:[elapsed-256],0000h ; Reset elapsed to zero
jmp int1c_isr_end ; Jump to IRET
int1c_isr_inc:
inc word ptr cs:[elapsed-256] ; Increment elapsed tick counter
int1c_isr_end:
iret ; Interrupt return from procedure
endmark: ; Used for TSR paragraph calc
install:
mov bx,cs ; Initialize DS & ES to equal CS
mov ds,bx
mov es,bx
mov ax,offset giveup_end ; Store size of full program into AX
mov cl,04h ; Divide AX by 4 to get paragraphs
shr ax,cl ; Paragraphs now in AX
inc ax ; Add one for good measure
mov bx,ax ; Paragraph size goes in BX
mov ax,4A00h ; DOS func 4A, Resize memory block
int 21h ; Call DOS
mov ah,49h ; DOS function 49h, release memory block
mov bx,2Ch ; Offset in PSP of program environment segment address
mov cx,word ptr es:[bx] ; Retrieve that segment address into CX
mov es,cx ; And load into ES
int 21h ; Call DOS
mov bx,cs ; Reset ES
mov es,bx
mov ah,09h ; DOS Print message function
mov dx,offset msg0 ; Print ownership message
int 21h ; Call DOS
install_chek: ; Check if already installed
mov ax,0BADDh ; GIVE-UP multiplex ID is BADDh
int 2Fh ; Call multiplex interrupt
cmp ax,0FADEh ; AX=FADEh GIVE-UP is installed
jne cmd_line ; If not installed the continue
jmp already_installed ; Do nothing and exit
cmd_line: ; Find trigger interval on command line
cld ; Clear direction flag (Count upward)
mov di,0080h ; Offset of command tail in PSP
mov cx,007Fh ; Length of command tail in PSP
mov al,0Dh ; Character to search for (CR first to prevent screwups w/OS2)
repne scasb ; Scan for CR
mov cx,di ; Move offset of CR into CX
sub cx,0080h ; Subtract 80h, this is new max scan length
mov di,0080h ; Offset of command tail in PSP
mov al,'/' ; Character to search for
repne scasb ; Scan for /
cmp cl,00h ; If CL = 0 then / was not found
je loader ; Load with default of every 4 ticks
mov word ptr cs:[whenmask],0000h ; Zero the trigger interval
mov al,byte ptr es:[di] ; Move the byte into AL
sub al,30h ; Convert from ASCII into a number
mov bl,10 ; Store 10 into BL
xor ah,ah ; Zero AH
mul bl ; Multiply by 10
add word ptr cs:[whenmask],ax ; Add it to the trigger interval
inc di ; Increment DI to next character
mov al,byte ptr es:[di] ; Move the byte into AL
sub al,30h ; Convert from ASCII into a number
xor ah,ah ; Zero AH
add word ptr cs:[whenmask],ax ; Add it to the trigger interval
loader: ; Install the ISRs and their data
mov ax,5800h ; DOS function 58, sub func 00, Get allocation strategy
int 21h ; Call DOS
mov word ptr cs:[strat],ax ; Store the current allocation strategy
mov ax,5801h ; DOS function 58, sub func 01, Set allocation strategy
mov bx,0002h ; To a last fit strategy
int 21h ; Call DOS
mov bx,offset start ; Get the offset of the start label
mov ax,offset endmark ; Get offset of the endmark label
sub ax,bx ; Find number of bytes between start and endmark
mov cl,04h ; Divide AX by 16 to get paragraphs
shr ax,cl ; Paragraphs now in AX
inc ax ; Just in case
mov bx,ax ; Store number of paragraphs into BX
mov ax,4800h ; DOS func. 48h, allocate memory
int 21h ; Call DOS
mov word ptr cs:[iseg],ax ; Store newly allocated segment address
mov ax,5801h ; DOS function 58, sub func 01, Set allocation strategy
mov bx,word ptr cs:[strat] ; Restore the current strategy
int 21h ; Call DOS
push es ; Preserve ES
mov ax,word ptr cs:[iseg] ; Load the ISR segment
dec ax ; Decrementing it points it to the correct MCB
mov es,ax ; Point ES to it
mov bx,0001h ; Offset in MCB of owner PID
mov word ptr es:[bx],0008h ; DOS' PID is always 8
pop es ; Restore ES
mov ax,offset int1c_isr ; Calculate the Int 1Ch isr offset
sub ax,256 ; By subtracting the PSP, the new offset is left
mov word ptr cs:[off1c],ax ; Store it out
mov ax,offset int28_isr ; Calculate the Int 28h isr offset
sub ax,256 ; By subtracting the PSP, the new offset is left
mov word ptr cs:[off28],ax ; Store it out
mov ax,offset int2f_isr ; Calculate the Int 2fh isr offset
sub ax,256 ; By subtracting the PSP, the new offset is left
mov word ptr cs:[off2f],ax ; Store it out
mov ax,3400h ; Int 21h, func 3400h, Get In-DOS flag address
int 21h ; Call DOS
mov word ptr [indos_flg],bx ; Offset of In-DOS flag
mov word ptr [indos_flg+2],es ; Segment of In-DOS flag
push ds ; Preserve DS
push si ; Preserve SI
mov ax,5D06h ; Int 21h, func 5D06h, Get DOS Swappable Data Area
int 21h ; Call DOS
mov word ptr [crter_flg],si ; Offset of Critical Error Flag
mov word ptr [crter_flg+2],ds ; Segment of Critical Error Flag
pop si ; Restore SI
pop ds ; Restore DS
mov ax,351Ch ; Save the current INT 1Ch handler address
int 21h ; Call DOS
mov word ptr [oldint1c],bx ; Offset of INT 1Ch ISR
mov word ptr [oldint1c+2],es ; Segment of INT 1Ch ISR
mov ax,3528h ; Save the current INT 28h handler address
int 21h ; Call DOS
mov word ptr [oldint28],bx ; Offset of INT 28h ISR
mov word ptr [oldint28+2],es ; Segment of INT 1Ch ISR
mov ax,352fh ; Save the current INT 2fh handler address
int 21h ; Call DOS
mov word ptr [oldint2f],bx ; Offset of INT 2fh ISR
mov word ptr [oldint2f+2],es ; Segment of INT 2fh ISR
push es ; Preserve ES
push ds ; Preserve DS
push di ; Preserve DI
push si ; Preserve SI
pushf ; Preserve the flags
mov bx,word ptr cs:[iseg] ; Point ES to the new ISR segment
mov es,bx
mov si,offset start ; DS:SI points to source
mov di,0000h ; ES:DI points to destination
mov bx,offset start ; BX holds start
mov ax,offset endmark ; AX holds endmark
sub ax,bx ; AX holds number of bytes to copy
mov cx,ax ; Now CX holds it
cld ; Copy goes from lo to hi
rep movsb ; Copy all of the ISR code and data to its new home
popf ; Restore the flags
pop si ; Restore SI
pop di ; Restore DI
pop ds ; Restore DS
pop es ; Restore ES
push ds ; Preserve DS
mov bx,word ptr cs:[iseg] ; Point DS to new ISR segment
mov ds,bx
mov ax,251Ch ; Insert my own Int 1Ch handler in ISR chain
mov dx,word ptr cs:[off1c] ; DS:DX points to ISR
int 21h ; Call DOS
mov ax,2528h ; Insert my own Int 1Ch handler in ISR chain
mov dx,word ptr cs:[off28] ; DS:DX points to ISR
int 21h ; Call DOS
mov ax,252fh ; Insert my own Int 2Fh handler in ISR chain
mov dx,word ptr cs:[off2f] ; DS:DX points to ISR
int 21h ; Call DOS
pop ds ; Restore DS
mov ax,4C00h ; Terminate with errorlevel=0
jmp exit ; And exit
already_installed:
mov ah,09h ; Print already installed message
mov dx,offset msg4
int 21h ; Call DOS
mov ax,4CFFh ; If no revectoring then errorlevel=255
exit: ; Terminate normally
int 21h ; Call DOS
; Data at end of code so it isn't kept when program goes TSR
strat dw 0000h ; DOS allocation strategy
iseg dw 0000h ; Segment allocated for ISRs and data
off1c dw 0000h ; Offset of int 1Ch isr
off28 dw 0000h ; Offset of int 28h isr
off2f dw 0000h ; Offset of int 2Fh isr
msg0 db 13,10,'GIVE-UP TSR for OS/2, WinNT, Win95 & WFW',13,10
msg1 db 'By: Paul Trout, Bionic Fish Software Foundry',13,10
msg2 db '23 Mar. 1996 -- V2R1',13,10,13,10,'$'
msg4 db 'GIVE-UP already installed, Not going TSR',13,10,'$'
giveup_end: ; True end of program marker
_CODE ENDS
END start